// Copyright (c) 2025 Huawei Technologies Co., Ltd.
// openUBMC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Description: 获取VMM相关信息

#include "GetVmmInfo.hpp"

GetVmmInfo::GetVmmInfo(KvmClient& client) : client_(client) {
    client.RegisterSendMessageHandler(CMD_GET_VMM_STATUS_REQ_C, [this](const std::vector<uint8_t>& body) {
        return SendGetVmmStatusReq(body);
    });

    client.RegisterRecvMessageHandler(CMD_GET_VMM_STATUS_RSP_S, [this](const std::vector<uint8_t>& body) {
        RecvGetVmmStatusRsp(body);
    });

    client.RegisterSendMessageHandler(CMD_GET_VMM_PORT_REQ_C, [this](const std::vector<uint8_t>& body) {
        return SendGetVmmPortReq(body);
    });

    client.RegisterRecvMessageHandler(CMD_GET_VMM_PORT_RSP_S, [this](const std::vector<uint8_t>& body) {
        RecvGetVmmPortRsp(body);
    });
}
GetVmmInfo::~GetVmmInfo() = default;

std::pair<int, std::vector<uint8_t>> GetVmmInfo::SendGetVmmStatusReq(const std::vector<uint8_t>& body) {
    try {
        // 发送连接请求后，等待服务端的响应
        std::unique_lock<std::mutex> rspLock(getVmmStatusMutex_);

        getVmmStatusRsp_ = 0xff; // 查询前置成无效值
        PackData pack_data;
        client_.Send(pack_data.GetVmmStatus());
        if (!getVmmStatusCv_.wait_for(rspLock, std::chrono::seconds(RESPONSE_TIMEOUT),
            [this]() { return getVmmStatusRsp_ != 0xff; })) {
                client_.LogMessage("GetVmmStatus: Timeout waiting for response.");
            return {E_TIMEOUT, {}};
        }

        return {E_OK, {getVmmStatusRsp_}};

    } catch(const std::exception& e) {
        client_.LogMessage(std::string("Exception in GetVmmStatus: ") + e.what());
        return {E_ERR, {}};
    }
}

void GetVmmInfo::RecvGetVmmStatusRsp(const std::vector<uint8_t>& body) {
    if (body.size() != 1) {
        client_.LogMessage("GetVmmStatus: Invalid response size.");
        return;
    }

    uint8_t rspCode = body[0];
    std::lock_guard<std::mutex> lock(getVmmStatusMutex_);
    getVmmStatusRsp_ = rspCode; // 根据响应码设置结果
    getVmmStatusCv_.notify_one(); // 通知等待的线程
}

std::pair<int, std::vector<uint8_t>> GetVmmInfo::SendGetVmmPortReq(const std::vector<uint8_t>& body) {
    try {
        // 发送连接请求后，等待服务端的响应
        std::unique_lock<std::mutex> rspLock(getVmmPortMutex_);

        getVmmPortRsp_ = {}; // 查询前置成无效值
        PackData pack_data;
        client_.Send(pack_data.GetVmmPort());
        if (!getVmmPortCv_.wait_for(rspLock, std::chrono::seconds(RESPONSE_TIMEOUT),
            [this]() { return !getVmmPortRsp_.empty(); })) {
                client_.LogMessage("GetVmmPort: Timeout waiting for response.");
            return {E_TIMEOUT, {}};
        }

        return {E_OK, getVmmPortRsp_};
    } catch(const std::exception& e) {
        client_.LogMessage(std::string("Exception in GetVmmPort: ") + e.what());
        return {E_ERR, {}};
    }
}

void GetVmmInfo::RecvGetVmmPortRsp(const std::vector<uint8_t>& body) {
    // 端口号长度为2字节
    if (body.size() != 2) {
        client_.LogMessage("GetVmmPort: Invalid response size.");
        return;
    }

    std::lock_guard<std::mutex> lock(getVmmPortMutex_);
    getVmmPortRsp_ = body; // 根据响应码设置结果
    getVmmPortCv_.notify_one(); // 通知等待的线程
}
